#include "main.h"
static int *total;                // 指向共享内存中数据节点总个数
static struct std_node *node_arr; // 指向共享内存中节点缓存数组头

#define MAX_NODE 128 // 最大支持学生数目
#define STD_NODE_LEN sizeof(struct std_node)
#define MAX_NODE_SIZE  32      //共享内存的大小
#define IP "192.168.51.112"  //主机IP
#define MSG "modbus"       //消息队列的名字

int msgid=0;
int main(int argc, char *argv[])
{
    // 1.创建实例
    ctx = modbus_new_tcp(IP, 502);
    // 2.设置从机ID
    modbus_set_slave(ctx, 1);
    // 3.建立连接
    int a = modbus_connect(ctx);
    if (a < 0)
    {
        perror("connect err\n");
        return -1;
    }
    printf("connect ok\n");
    //int msgid= msg_init();
    // 创建线程
    pthread_t tid, pid;
    if (pthread_create(&tid, NULL, collection_h, NULL) != 0) // 采集数据
    {
        perror("collection create err\n");
        return -1;
    }
    if (pthread_create(&pid, NULL, control_h, NULL) != 0) // 控制指令下发
    {
        perror("control create err\n");
        return -1;
    }
    while (1)
        ;
    modbus_free(ctx);
    // 关闭套接字
    modbus_close(ctx);
    pthread_detach(tid);
    pthread_detach(pid);
    return 0;
}

void *collection_h(void *arg)
{

    int ret = -1;
    ret=shm_init(MAX_NODE_SIZE);
    if (ret < 0)
    {
        perror("ret err\n");
        return NULL;
    }

    void *node_p = shm_getaddr();
    if (node_p == NULL)
    {
        perror("nnode_p err\n");
        return NULL;
    }

    // 前4个字节存储实际的学生数目
    total = (int *)node_p;
    // 后面空间存储数据点
    node_arr = (struct std_node *)(node_p + sizeof(int));

    printf("num = %d\n", *total);
    int i;
    for (i = 0; i < *total; i++)
    {
        printf("key=%d\n", node_arr[i].key);
    }
    while (1)
    {
        // 1从设备上采集数据线圈
        uint8_t dest[16] = {0};
        modbus_read_bits(ctx, 0, 4, dest);
        // 从保持寄存器采集数据
        uint16_t data[16]={0};
        modbus_read_registers(ctx,0,1,data);
        for (int i = 0; i < *total; i++)
        {
            if (node_arr[i].key == 104)
            {
                node_arr[i].new_val.i_val = dest[0];
               
            }
            if (node_arr[i].key == 103)
            {
                node_arr[i].new_val.i_val = dest[1];
                 printf("103:%d\n",node_arr[i].new_val.i_val);
            }
            if (node_arr[i].key == 102)
            {
                node_arr[i].new_val.i_val = dest[2];
            }
            if (node_arr[i].key == 101)
            {
                node_arr[i].new_val.i_val = data[0];
            }
        }
        for (int i = 0; i < *total; i++)
        {
            if ((node_arr + i)->key == 104)
            {
                printf("101: %d ", (node_arr + i)->new_val.i_val);
            }
            if ((node_arr + i)->key == 103)
            {
                printf("102: %d ", (node_arr + i)->new_val.i_val);
            }

            if ((node_arr + i)->key == 102)
            {
                printf("103: %d ", (node_arr + i)->new_val.i_val);
            }
            if ((node_arr + i)->key == 101)
            {
                printf("104: %d ", (node_arr + i)->new_val.i_val);
            }
        }
        sleep(1);
     }
    pthread_exit(NULL);
}

void *control_h(void *arg)
{
    struct msgbuf msgbuf;
    while (1)
    {
        printf("进入消息队列\n");
        //用消息队列接收指令
         if (msg_queue_recv(MSG, &msgbuf, sizeof(struct msgbuf), 102, 0) == -1)
        {
            perror("msg_queue_recv error");
            continue; // 如果接收失败，跳过本次循环
        }
    
       
        int set_key;
        int set_val;
        sscanf(msgbuf.mdata, "key:%d,val:%d", &set_key, &set_val);
         printf("msg1.key=%s\n", msgbuf.mdata);
        //printf("key:%ls,val:%ls", &set_key, &set_val);
        // 将消息队列中的数值下发至设备上，并容错判断
        switch (set_key)
        {
        case 104:
            if (modbus_write_bit(ctx, 0, set_val) == -1)
            {
                perror("modbus_write_bit error on address 0");
            }
            break;
        case 103:
            if (modbus_write_bit(ctx, 2, set_val) == -1)
            {
                perror("modbus_write_bit error on address 1");
            }
            break;
        case 102:
            if (modbus_write_bit(ctx, 1, set_val) == -1)
            {
                perror("modbus_write_bit error on address 2");
            }
            break;
        case 101:
            if ( modbus_write_register(ctx, 0, set_val) == -1)
            {
                perror("modbus_write_bit error on address 3");
            }
            break;
        default:
            printf("Invalid key received: %d\n", set_key);
            break;
        }
    }
    pthread_exit(NULL);
}
